﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO; // 用于文件操作
using System.Linq;
using System.Text; // 用于 StringBuilder
using System.Windows.Forms; // 用于 SaveFileDialog，需要引用
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Analysis;   // HVACLoadSpaceType 在这里
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;

// --- 使用别名避免冲突 ---
using WinForms = System.Windows.Forms;

namespace RevitApiExample // 请确保与您项目的命名空间一致
{
    //====================================================================
    // 主命令类: ExportSpaceTypesCommand
    //====================================================================
    [Transaction(TransactionMode.Manual)] // 导出通常不需要修改模型，设为只读模式
    [Regeneration(RegenerationOption.Manual)]
    public class ExportSpaceTypesCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Document doc = uidoc.Document;

            // --- 1. 获取所有空间类型 ---
            List<HVACLoadSpaceType> allSpaceTypes;
            try
            {
                allSpaceTypes = new FilteredElementCollector(doc)
                    .OfClass(typeof(HVACLoadSpaceType))
                    .Cast<HVACLoadSpaceType>()
                    .OrderBy(st => st.Name) // 按名称排序
                    .ToList();

                if (!allSpaceTypes.Any())
                {
                    TaskDialog.Show("信息", "项目中没有找到任何 HVAC 空间类型可供导出。");
                    return Result.Succeeded;
                }
            }
            catch (Exception ex)
            {
                message = $"获取空间类型时出错: {ex.Message}";
                TaskDialog.Show("错误", message);
                return Result.Failed;
            }


            // --- 2. 获取用户指定的保存路径 ---
            string filePath = string.Empty;
            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
            {
                saveFileDialog.Filter = "CSV 文件 (*.csv)|*.csv|所有文件 (*.*)|*.*";
                saveFileDialog.Title = "选择保存空间类型 CSV 文件的位置";
                saveFileDialog.FileName = "ExportedSpaceTypes.csv"; // 默认文件名

                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    filePath = saveFileDialog.FileName;
                }
                else
                {
                    return Result.Cancelled; // 用户取消保存
                }
            }

            // --- 3. 构建 CSV 内容 ---
            StringBuilder csvContent = new StringBuilder();

            // 添加表头 (与导入格式匹配)
            string[] headers = {
                "Name", "IsPlenum", "AreaPerPerson_m2_person", "LightingLoadDensity_W_m2",
                "PowerLoadDensity_W_m2", "SensibleHeatGainPerPerson_W", "LatentHeatGainPerPerson_W",
                "HeatingSetpoint_C", "CoolingSetpoint_C"
            };
            csvContent.AppendLine(string.Join(",", headers));

            // 添加数据行
            foreach (var type in allSpaceTypes)
            {
                try
                {
                    // 读取属性并进行单位转换 (从内部单位 -> 显示/导出单位)
                    string name = EscapeCsvField(type.Name); // 处理名称中的特殊字符
                    string isPlenum = type.IsPlenum ? "TRUE" : "FALSE"; // 布尔值转为大写字符串

                    // 人均面积 (ft² -> m²)
                    double areaM2 = 0;
                    if (type.AreaPerPerson > 1e-9)
                        areaM2 = UnitUtils.ConvertFromInternalUnits(type.AreaPerPerson, UnitTypeId.SquareFeet);

                    // 照明负荷密度 (W/ft² -> W/m²)
                    double lightW_m2 = UnitUtils.ConvertFromInternalUnits(type.LightingLoadDensity, UnitTypeId.WattsPerSquareFoot);

                    // 设备负荷密度 (W/ft² -> W/m²)
                    double powerW_m2 = UnitUtils.ConvertFromInternalUnits(type.PowerLoadDensity, UnitTypeId.WattsPerSquareFoot);

                    // 人员显热 (Watts -> W) - 基于之前的发现，内部是Watts
                    double sensibleW = type.SensibleHeatGainPerPerson;

                    // 人员潜热 (Watts -> W) - 基于之前的发现，内部是Watts
                    double latentW = type.LatentHeatGainPerPerson;

                    // 供暖设定点 (K 或 R -> °C)
                    double heatC = UnitUtils.ConvertFromInternalUnits(type.HeatingSetPoint, UnitTypeId.Celsius);

                    // 制冷设定点 (K 或 R -> °C)
                    double coolC = UnitUtils.ConvertFromInternalUnits(type.CoolingSetPoint, UnitTypeId.Celsius);

                    // 格式化数值为字符串 (使用固定区域性避免小数点问题)
                    string areaStr = areaM2.ToString("F2", CultureInfo.InvariantCulture);
                    string lightStr = lightW_m2.ToString("F2", CultureInfo.InvariantCulture);
                    string powerStr = powerW_m2.ToString("F2", CultureInfo.InvariantCulture);
                    string sensibleStr = sensibleW.ToString("F2", CultureInfo.InvariantCulture);
                    string latentStr = latentW.ToString("F2", CultureInfo.InvariantCulture);
                    string heatStr = heatC.ToString("F1", CultureInfo.InvariantCulture);
                    string coolStr = coolC.ToString("F1", CultureInfo.InvariantCulture);

                    // 构建行数据
                    string[] row = {
                        name, isPlenum, areaStr, lightStr, powerStr,
                        sensibleStr, latentStr, heatStr, coolStr
                    };
                    csvContent.AppendLine(string.Join(",", row));
                }
                catch (Exception ex)
                {
                    // 处理单个类型导出时可能发生的错误 (例如单位转换失败)
                    System.Diagnostics.Debug.WriteLine($"导出类型 '{type.Name}' (ID: {type.Id}) 时出错: {ex.Message}");
                    // 可以选择跳过这个类型或中止整个导出
                    message = $"导出类型 '{type.Name}' 时发生错误，操作可能未完成。错误: {ex.Message}";
                    // TaskDialog.Show("导出错误", message); // 避免弹窗过多
                    // return Result.Failed; // 或者选择中止
                }
            }

            // --- 4. 写入文件 ---
            try
            {
                // 使用 UTF-8 编码 (带 BOM，提高 Excel 兼容性)
                File.WriteAllText(filePath, csvContent.ToString(), new UTF8Encoding(true));
            }
            catch (Exception ex)
            {
                message = $"无法将数据写入文件 '{filePath}'. 错误: {ex.Message}";
                TaskDialog.Show("文件写入错误", message);
                return Result.Failed;
            }

            // --- 5. 显示成功信息 ---
            TaskDialog.Show("导出成功", $"空间类型数据已成功导出到:\n{filePath}");
            return Result.Succeeded;
        }

        /// <summary>
        /// 对 CSV 字段进行转义处理，以防包含逗号、引号或换行符。
        /// </summary>
        /// <param name="field">要转义的字段字符串。</param>
        /// <returns>转义后的 CSV 字段字符串。</returns>
        private string EscapeCsvField(string field)
        {
            if (string.IsNullOrEmpty(field)) return "";

            // 如果字段包含逗号、双引号或换行符，则需要用双引号包围
            if (field.Contains(",") || field.Contains("\"") || field.Contains("\n") || field.Contains("\r"))
            {
                // 将字段内部的双引号替换为两个双引号
                string escapedField = field.Replace("\"", "\"\"");
                return $"\"{escapedField}\"";
            }
            // 否则，字段可以直接使用
            return field;
        }
    }
} // end namespace